import pygame
import random
import sys
import os
import json
from datetime import datetime

# 初始化pygame
pygame.init()

# 游戏常量
WIDTH, HEIGHT = 600, 600
GRID_SIZE = 20
GRID_WIDTH = WIDTH // GRID_SIZE
GRID_HEIGHT = HEIGHT // GRID_SIZE
FPS = 10

# 颜色定义
BLACK = (0, 0, 0)
WHITE = (255, 255, 255)
GREEN = (0, 255, 0)
RED = (255, 0, 0)
BLUE = (0, 0, 255)
GRAY = (128, 128, 128)
YELLOW = (255, 255, 0)
PURPLE = (128, 0, 128)

# 方向常量
UP = (0, -1)
DOWN = (0, 1)
LEFT = (-1, 0)
RIGHT = (1, 0)

# 分数文件路径
SCORE_FILE = os.path.join(os.path.dirname(__file__), "high_scores.json")

class ScoreManager:
    def __init__(self):
        self.scores = self.load_scores()
    
    def load_scores(self):
        try:
            if os.path.exists(SCORE_FILE):
                with open(SCORE_FILE, 'r', encoding='utf-8') as f:
                    return json.load(f)
        except:
            pass
        return []
    
    def save_score(self, score):
        self.scores.append({
            'score': score,
            'timestamp': datetime.now().strftime('%Y-%m-%d %H:%M:%S')
        })
        # 只保留前10个最高分
        self.scores.sort(key=lambda x: x['score'], reverse=True)
        self.scores = self.scores[:10]
        
        try:
            with open(SCORE_FILE, 'w', encoding='utf-8') as f:
                json.dump(self.scores, f, ensure_ascii=False, indent=2)
        except:
            pass

class Snake:
    def __init__(self):
        self.reset()
    
    def reset(self):
        self.length = 3
        self.positions = [(GRID_WIDTH // 2, GRID_HEIGHT // 2)]
        self.direction = RIGHT
        self.score = 0
        # 初始化蛇身
        for i in range(1, self.length):
            self.positions.append((self.positions[0][0] - i, self.positions[0][1]))
    
    def get_head_position(self):
        return self.positions[0]
    
    def move(self, obstacles):
        head = self.get_head_position()
        x, y = self.direction
        new_x = (head[0] + x) % GRID_WIDTH
        new_y = (head[1] + y) % GRID_HEIGHT
        new_position = (new_x, new_y)
        
        # 检查是否撞到自己
        if new_position in self.positions[1:]:
            return False
        
        # 检查是否撞到障碍物
        if new_position in obstacles:
            return False
        
        self.positions.insert(0, new_position)
        if len(self.positions) > self.length:
            self.positions.pop()
        return True
    
    def grow(self):
        self.length += 1
        self.score += 10
    
    def change_direction(self, direction):
        # 防止反向移动
        if (direction[0] * -1, direction[1] * -1) != self.direction:
            self.direction = direction

class Food:
    def __init__(self):
        self.position = (0, 0)
        self.randomize_position()
    
    def randomize_position(self, snake_positions=None, obstacles=None):
        snake_positions = snake_positions or []
        obstacles = obstacles or []
        while True:
            self.position = (random.randint(0, GRID_WIDTH - 1), 
                           random.randint(0, GRID_HEIGHT - 1))
            if self.position not in snake_positions and self.position not in obstacles:
                break

class Obstacle:
    def __init__(self):
        self.positions = []
        self.generate_obstacles()
    
    def generate_obstacles(self, snake_positions=None, food_position=None):
        snake_positions = snake_positions or []
        food_position = food_position or (-1, -1)
        self.positions = []
        
        # 生成5-8个障碍物
        num_obstacles = random.randint(5, 8)
        for _ in range(num_obstacles):
            while True:
                pos = (random.randint(0, GRID_WIDTH - 1), 
                      random.randint(0, GRID_HEIGHT - 1))
                if (pos not in snake_positions and 
                    pos != food_position and 
                    pos not in self.positions):
                    self.positions.append(pos)
                    break

class Game:
    def __init__(self):
        self.screen = pygame.display.set_mode((WIDTH, HEIGHT))
        pygame.display.set_caption("贪吃蛇游戏")
        self.clock = pygame.time.Clock()
        self.score_manager = ScoreManager()
        self.state = "menu"  # menu, playing, game_over, high_scores
        
        # 尝试加载中文字体，如果失败则使用默认字体
        try:
            # 尝试常见的中文字体
            chinese_fonts = [
                "C:\\Windows\\Fonts\\msyh.ttc",  # 微软雅黑
                "C:\\Windows\\Fonts\\simhei.ttf",  # 黑体
                "C:\\Windows\\Fonts\\simsun.ttc",  # 宋体
                "C:\\Windows\\Fonts\\simkai.ttf",  # 楷体
                "C:\\Windows\\Fonts\\Deng.ttf",   # 等线
            ]
            
            self.font = None
            self.small_font = None
            
            for font_path in chinese_fonts:
                try:
                    self.font = pygame.font.Font(font_path, 36)
                    self.small_font = pygame.font.Font(font_path, 24)
                    # 测试字体是否能渲染中文
                    test_surface = self.font.render("测试", True, (255, 255, 255))
                    if test_surface.get_width() > 0:
                        print(f"使用字体: {font_path}")
                        break
                except:
                    continue
            
            # 如果所有中文字体都失败，使用默认字体
            if self.font is None:
                print("警告：无法加载中文字体，使用默认字体")
                self.font = pygame.font.Font(None, 36)
                self.small_font = pygame.font.Font(None, 24)
        except:
            print("警告：字体加载失败，使用默认字体")
            self.font = pygame.font.Font(None, 36)
            self.small_font = pygame.font.Font(None, 24)
        
        self.reset_game()
    
    def reset_game(self):
        self.snake = Snake()
        self.food = Food()
        self.obstacles = Obstacle()
        self.game_over = False
        
        # 重新生成障碍物，避开蛇和食物
        self.obstacles.generate_obstacles(self.snake.positions, self.food.position)
        # 确保食物不在障碍物上
        self.food.randomize_position(self.snake.positions, self.obstacles.positions)
    
    def handle_menu_events(self):
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                pygame.quit()
                sys.exit()
            elif event.type == pygame.KEYDOWN:
                if event.key == pygame.K_1:
                    self.state = "playing"
                elif event.key == pygame.K_2:
                    self.state = "high_scores"
                elif event.key == pygame.K_3:
                    pygame.quit()
                    sys.exit()
    
    def handle_game_events(self):
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                pygame.quit()
                sys.exit()
            elif event.type == pygame.KEYDOWN:
                if event.key == pygame.K_ESCAPE:
                    self.state = "menu"
                elif event.key == pygame.K_UP:
                    self.snake.change_direction(UP)
                elif event.key == pygame.K_DOWN:
                    self.snake.change_direction(DOWN)
                elif event.key == pygame.K_LEFT:
                    self.snake.change_direction(LEFT)
                elif event.key == pygame.K_RIGHT:
                    self.snake.change_direction(RIGHT)
    
    def handle_game_over_events(self):
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                pygame.quit()
                sys.exit()
            elif event.type == pygame.KEYDOWN:
                if event.key == pygame.K_r:
                    self.reset_game()
                    self.state = "playing"
                elif event.key == pygame.K_m:
                    self.state = "menu"
    
    def handle_high_scores_events(self):
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                pygame.quit()
                sys.exit()
            elif event.type == pygame.KEYDOWN:
                if event.key == pygame.K_ESCAPE:
                    self.state = "menu"
    
    def update(self):
        if not self.snake.move(self.obstacles.positions):
            self.game_over = True
            self.score_manager.save_score(self.snake.score)
            self.state = "game_over"
            return
        
        # 检查是否吃到食物
        if self.snake.get_head_position() == self.food.position:
            self.snake.grow()
            self.food.randomize_position(self.snake.positions, self.obstacles.positions)
    
    def draw_menu(self):
        self.screen.fill(BLACK)
        
        title = self.font.render("贪吃蛇游戏", True, GREEN)
        title_rect = title.get_rect(center=(WIDTH//2, HEIGHT//4))
        self.screen.blit(title, title_rect)
        
        option1 = self.font.render("1. 开始游戏", True, WHITE)
        option1_rect = option1.get_rect(center=(WIDTH//2, HEIGHT//2 - 50))
        self.screen.blit(option1, option1_rect)
        
        option2 = self.font.render("2. 查看历史分数", True, WHITE)
        option2_rect = option2.get_rect(center=(WIDTH//2, HEIGHT//2))
        self.screen.blit(option2, option2_rect)
        
        option3 = self.font.render("3. 退出游戏", True, WHITE)
        option3_rect = option3.get_rect(center=(WIDTH//2, HEIGHT//2 + 50))
        self.screen.blit(option3, option3_rect)
        
        pygame.display.flip()
    
    def draw_game(self):
        self.screen.fill(BLACK)
        
        # 绘制网格
        for x in range(0, WIDTH, GRID_SIZE):
            pygame.draw.line(self.screen, (40, 40, 40), (x, 0), (x, HEIGHT))
        for y in range(0, HEIGHT, GRID_SIZE):
            pygame.draw.line(self.screen, (40, 40, 40), (0, y), (WIDTH, y))
        
        # 绘制障碍物
        for pos in self.obstacles.positions:
            rect = pygame.Rect(pos[0] * GRID_SIZE, pos[1] * GRID_SIZE, 
                             GRID_SIZE, GRID_SIZE)
            pygame.draw.rect(self.screen, GRAY, rect)
            pygame.draw.rect(self.screen, WHITE, rect, 1)
        
        # 绘制蛇
        for i, pos in enumerate(self.snake.positions):
            color = GREEN if i == 0 else BLUE
            rect = pygame.Rect(pos[0] * GRID_SIZE, pos[1] * GRID_SIZE, 
                             GRID_SIZE, GRID_SIZE)
            pygame.draw.rect(self.screen, color, rect)
            pygame.draw.rect(self.screen, BLACK, rect, 1)
        
        # 绘制食物
        food_rect = pygame.Rect(self.food.position[0] * GRID_SIZE, 
                              self.food.position[1] * GRID_SIZE, 
                              GRID_SIZE, GRID_SIZE)
        pygame.draw.rect(self.screen, RED, food_rect)
        
        # 显示分数
        score_text = self.font.render(f"得分: {self.snake.score}", True, WHITE)
        self.screen.blit(score_text, (10, 10))
        
        # 显示提示
        hint_text = self.small_font.render("按ESC返回菜单", True, WHITE)
        self.screen.blit(hint_text, (WIDTH - 150, 10))
        
        pygame.display.flip()
    
    def draw_game_over(self):
        self.screen.fill(BLACK)
        
        game_over_text = self.font.render("游戏结束!", True, RED)
        score_text = self.font.render(f"最终得分: {self.snake.score}", True, WHITE)
        restart_text = self.font.render("按R键重新开始", True, YELLOW)
        menu_text = self.font.render("按M键返回菜单", True, YELLOW)
        
        game_over_rect = game_over_text.get_rect(center=(WIDTH//2, HEIGHT//2 - 60))
        score_rect = score_text.get_rect(center=(WIDTH//2, HEIGHT//2 - 20))
        restart_rect = restart_text.get_rect(center=(WIDTH//2, HEIGHT//2 + 20))
        menu_rect = menu_text.get_rect(center=(WIDTH//2, HEIGHT//2 + 60))
        
        self.screen.blit(game_over_text, game_over_rect)
        self.screen.blit(score_text, score_rect)
        self.screen.blit(restart_text, restart_rect)
        self.screen.blit(menu_text, menu_rect)
        
        pygame.display.flip()
    
    def draw_high_scores(self):
        self.screen.fill(BLACK)
        
        title = self.font.render("历史最高分", True, GREEN)
        title_rect = title.get_rect(center=(WIDTH//2, 50))
        self.screen.blit(title, title_rect)
        
        if not self.score_manager.scores:
            no_scores = self.font.render("暂无记录", True, WHITE)
            no_scores_rect = no_scores.get_rect(center=(WIDTH//2, HEIGHT//2))
            self.screen.blit(no_scores, no_scores_rect)
        else:
            for i, score_data in enumerate(self.score_manager.scores):
                score_text = f"{i+1}. {score_data['score']}分 - {score_data['timestamp']}"
                text = self.small_font.render(score_text, True, WHITE)
                text_rect = text.get_rect(center=(WIDTH//2, 100 + i * 30))
                self.screen.blit(text, text_rect)
        
        hint_text = self.small_font.render("按ESC返回菜单", True, YELLOW)
        hint_rect = hint_text.get_rect(center=(WIDTH//2, HEIGHT - 50))
        self.screen.blit(hint_text, hint_rect)
        
        pygame.display.flip()
    
    def run(self):
        while True:
            if self.state == "menu":
                self.handle_menu_events()
                self.draw_menu()
            elif self.state == "playing":
                self.handle_game_events()
                self.update()
                self.draw_game()
            elif self.state == "game_over":
                self.handle_game_over_events()
                self.draw_game_over()
            elif self.state == "high_scores":
                self.handle_high_scores_events()
                self.draw_high_scores()
            
            self.clock.tick(FPS)

if __name__ == "__main__":
    game = Game()
    game.run()